using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using JetBrains.Annotations;

namespace com.susi.ui {
    public abstract class ViewModel : INotifyPropertyChanged, IDisposable {
        private static Dictionary<Type, (ViewModel vm, int count)> ViewModelsLoaded = new Dictionary<Type, (ViewModel vm, int count)>();

        public event PropertyChangedEventHandler PropertyChanged;

        public bool IsDisposed { get; private set; }

        public void Dispose()
        {
            if (IsDisposed) return;
            IsDisposed      = true;
            PropertyChanged = null;
        }

        [NotifyPropertyChangedInvocator]
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public static T Load<T>() where T : ViewModel, new()
        {
            var type = typeof(T);
            if (ViewModelsLoaded.TryGetValue(type, out var tuple)) {
                tuple.count++;
                ViewModelsLoaded[type] = tuple;
                return (T) (tuple.vm);
            }

            tuple = (new T(), 1);
            ViewModelsLoaded.Add(type, tuple);
            return (T) (tuple.vm);
        }

        public static void Unload<T>(T obj) where T : ViewModel
        {
            var type = typeof(T);
            if (ViewModelsLoaded.TryGetValue(type, out var tuple)) {
                tuple.count--;
                if (tuple.count <= 0) {
                    tuple.vm.Dispose();
                    ViewModelsLoaded.Remove(type);
                }
                else {
                    ViewModelsLoaded[type] = tuple;
                }
            }
        }
    }
}